﻿using System;
using UnityEngine;
using System.Collections.Generic;

namespace LightGameLibs
{
    /// <summary>
    /// 获取本地Json文件内容的类
    /// </summary>
    public static class LocalDatabase
    {
        private static Dictionary<DBTag, Dictionary<int, DBElement>> s_index2DatabaseDict = new Dictionary<DBTag, Dictionary<int, DBElement>>();
        public const string c_defaultPath = "LightGameLibs/LocalDBConfig";
        private static Dictionary<DBTag, DBTextAsset> s_tag2TextDict;

        public static T GetData<T>(DBTag tag, int index) where T : DBElement
        {
            Dictionary<int, DBElement> elemDict = null;
            if (!s_index2DatabaseDict.TryGetValue(tag, out elemDict) && !InitDatabase<T>(tag))
            {
                return null;
            }

            DBElement elem = null;
            if (!elemDict.TryGetValue(index, out elem))
            {
                DebugMgr.Log(DebugTag.LOCALDATABASE, "Element Not Exist In The Database");
                return null;
            }

            return (T)elem;
        }

        public static Dictionary<int, T> GetDatabase<T>(DBTag tag) where T : DBElement
        {
            Dictionary<int, DBElement> elemDict = null;
            if (!s_index2DatabaseDict.TryGetValue(tag, out elemDict) && !InitDatabase<T>(tag))
            {
                return null;
            }

            var resultDict = new Dictionary<int, T>();
            foreach (var item in elemDict)
            {
                resultDict.Add(item.Key, (T)item.Value);
            }

            return resultDict;
        }

        public static void InitAllDatabase(bool isForce = false)
        {
            if (!CheckDBConfig())
            {
                return;
            }

            var method = typeof(LocalDatabase).GetMethod("InitDatabase");
            foreach (var item in s_tag2TextDict)
            {
                if (s_index2DatabaseDict.ContainsKey(item.Key) || (!isForce && !item.Value.m_isPreInit))
                {
                    continue;
                }
                var elementType = System.Reflection.Assembly.Load(item.Value.m_assemblyName).GetType(item.Value.m_typeName);

                var genericMethod = method.MakeGenericMethod(elementType);
                genericMethod.Invoke(null, new object[] { item.Key });
            }
        }

        private static bool InitDatabase<T>(DBTag tag) where T : DBElement
        {
            if (!CheckDBConfig())
            {
                return false;
            }

            var targetDB = ReadDatabase<T>(tag);
            if (null == targetDB)
            {
                return false;
            }

            s_index2DatabaseDict.Add(tag, targetDB);
            return true;
        }

        private static bool CheckDBConfig()
        {
            if (null == s_tag2TextDict)
            {
                var DBConfig = (LocalDBConfig)Resources.Load(c_defaultPath, typeof(LocalDBConfig));
                if (null == DBConfig)
                {
                    DebugMgr.Log(DebugTag.LOCALDATABASE, "Cant find DBConfig");
                    return false;
                }
                s_tag2TextDict = DBConfig.Tag2TextDict.GetRawDict();
            }

            return true;
        }

        private static Dictionary<int, DBElement> ReadDatabase<T>(DBTag tag) where T : DBElement
        {
            DBTextAsset asset = null;
            if (!s_tag2TextDict.TryGetValue(tag, out asset))
            {
                DebugMgr.Log(DebugTag.LOCALDATABASE, "Database Not Exist In Config");
                return null;
            }

            var resultDict = new Dictionary<int, DBElement>();
            var resultArray = ArrayJsonUtility.FromJson<T>(asset.m_text.text);

            if (null == resultArray)
            {
                resultArray = new T[0];
            }

            for (int i = 0, length = resultArray.Length; i < length; i++)
            {
                resultDict.Add(resultArray[i].ID, resultArray[i]);
            }

            return resultDict;
        }
    }
}
